//updated by wei 2012/05/20 for computing the 2 distance similaries.


#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include <ctime>

using namespace std;

int main(int argc, char* argv[]) {
	srand((unsigned)time(0));
	float r = (float)rand()/(float)RAND_MAX;
	cout << "r: " << r << endl;
	exit(1);

	/*
	// maybe NOT passed.
	cout << "Debug Begins..." << endl;
	// write operation
	// allocate this piece of memory and maintain it
	int num_postings_in_current_doc_in_test = 10;
	int BIG_NUMBER_in_test = 50000000;
	IndexDocOptimizedEntry* index_doc_entry_buffer = new IndexDocOptimizedEntry[num_postings_in_current_doc_in_test];

	// init the value as well. Otherwise, the value will be just random.
	// for(int index_doc_entry_offset = 0; index_doc_entry_offset < num_postings_in_current_doc_in_test; index_doc_entry_offset++){
	for(int index_doc_entry_offset = 0; index_doc_entry_offset <= 2 * num_postings_in_current_doc_in_test; index_doc_entry_offset++){
		  IndexDocOptimizedEntry& curr_index_doc_entry = index_doc_entry_buffer[index_doc_entry_offset];
		  // assert(index_doc_entry_offset < num_postings_in_current_doc_in_test);
		  curr_index_doc_entry.term_id = BIG_NUMBER_in_test; // Not Very Proper cause 0 actually represent another term
		  curr_index_doc_entry.staticProbability = index_doc_entry_offset;
	}

	// read operation
	for(int index_doc_entry_offset = 0; index_doc_entry_offset <= 2 * num_postings_in_current_doc_in_test; index_doc_entry_offset++){
		  cout << "index_doc_entry_offset: " << index_doc_entry_offset << endl;
		  cout << "term_id: " << index_doc_entry_buffer[index_doc_entry_offset].term_id << endl;
		  cout << "staticProbability:" << index_doc_entry_buffer[index_doc_entry_offset].staticProbability << endl;
		  cout << endl;
	}
	cout << "Debug Ends." << endl;
	exit(1);
	*/


	/*
	cout << "Program Begins..." << endl;
	// TODO: It's better to reuse the buffer, and resize only when necessary.
	// Load the thing into the main memory cause I need to sort them
	vector<int>* vector_list_entry_buffer = new vector<int>[1];

	vector<int>& curr_vector_entry = vector_list_entry_buffer[0];
	curr_vector_entry.push_back(0);

	curr_vector_entry = vector_list_entry_buffer[1];
	curr_vector_entry.push_back(1);

	// assert(index_list_entry_offset < num_docs_in_original_list);

	cout << "Program Ends." << endl;
	exit(1);
	*/

	/*
	cout << "Let's do sth." << endl;
	cout << "Program Begins..." << endl;

    int myints[] = {10,20,30,5,15};
    vector<int> v(myints,myints+5);

    make_heap (v.begin(),v.end());
    cout << "initial max heap   : " << v.front() << '\n';

    pop_heap (v.begin(),v.end()); v.pop_back();
    cout << "max heap after pop : " << v.front() << '\n';

    pop_heap (v.begin(),v.end()); v.pop_back();
    cout << "max heap after pop : " << v.front() << '\n';

    pop_heap (v.begin(),v.end()); v.pop_back();
    cout << "max heap after pop : " << v.front() << '\n';

    pop_heap (v.begin(),v.end()); v.pop_back();
    cout << "max heap after pop : " << v.front() << '\n';
    */

    /*
    v.push_back(99); std::push_heap (v.begin(),v.end());
    std::cout << "max heap after push: " << v.front() << '\n';

    std::sort_heap (v.begin(),v.end());

    std::cout << "final sorted range :";
    for (unsigned i=0; i<v.size(); i++){
    	std::cout << ' ' << v[i];
    }
    std::cout << '\n';
	cout << "Program Ends." << endl;
	*/

	/*
	string inputFileName = "/data1/team/sergeyn/quant/filesListed.txt";
	string outputFileName = "/data1/team/sergeyn/quant/similaryResult.txt";
	ofstream outputFileHandler(outputFileName.c_str());
	outputFileHandler << "Term,Length,RMSD" << "\n";

	string currentLine;
	ifstream inputfile(inputFileName.c_str());
	vector<string> fileNames;
	vector<string>::iterator fileNamesIterator;
	while ( inputfile.good() )
	{
		getline (inputfile,currentLine);
		if(currentLine != ""){
		    boost::algorithm::trim(currentLine);
		    cout << currentLine << endl;
		    fileNames.push_back(currentLine);
		}
	}
	inputfile.close();
	cout << fileNames.size() << endl;

	string basePath = "/data1/team/weijiang/machine-learning-project-related/featuresGenerated/individualTermBM25ScoreLists/";

	string BM25ScoresInputFileName = "";
	int processingNUmberCounter = 0;
	for(fileNamesIterator = fileNames.begin(); fileNamesIterator != fileNames.end(); fileNamesIterator++)
	{
		processingNUmberCounter ++;
	    BM25ScoresInputFileName = basePath + *fileNamesIterator;
	    cout << processingNUmberCounter << " Processing Term:" << *fileNamesIterator << endl;

	    outputFileHandler << processingNUmberCounter;
	    outputFileHandler << ",";
	    outputFileHandler << *fileNamesIterator;
	    outputFileHandler << ",";

		ifstream inputfile2(BM25ScoresInputFileName.c_str());
		vector<float> BM25ScoreList;
		vector<float> BM25ScoreQuantizedScoreList;
		while ( inputfile2.good() )
		{
			getline (inputfile2,currentLine);
			if(currentLine != ""){
			    boost::algorithm::trim(currentLine);
			    //cout << currentLine << endl;
			    BM25ScoreList.push_back(atof(currentLine.c_str()));
			}
		}
		inputfile2.close();
		cout << "Length of the BM25 Score list:" << BM25ScoreList.size() << endl;
		outputFileHandler << BM25ScoreList.size();
		outputFileHandler << ",";

		//This is just a check.
		//for(int i=0; i< BM25ScoreList.size(); i++){
		//	cout << BM25ScoreList[i] << endl;
		//}

		sort(BM25ScoreList.begin(),BM25ScoreList.end()); //!! must sort before running quant

		// Quantization method1
		//Quant<AvgSelector<floatVecIt>, FastSplitter<TriangleWeighter<DiffSelector<floatVecIt> > > > quant;

		// Quantization method2
		Quant<AvgSelector<floatVecIt>, FastSplitter<TieSumWeighter > > quant;

		quant(BM25ScoreList.begin(),BM25ScoreList.end(),256);


		for(int i=0; i < BM25ScoreList.size(); i++){
			//cout << BM25ScoreList[i] << " ";
			BM25ScoreQuantizedScoreList.push_back( quant[quant.make(BM25ScoreList[i])] );
			//cout << (quant.make(BM25ScoreList[i])) << endl;
		}

		//Similarity Mesaure Method 1
		//Let's compute the Root-mean-square deviation here.
		//The fomula is based on: http://en.wikipedia.org/wiki/Cosine_similarity
		if (BM25ScoreList.size() != BM25ScoreQuantizedScoreList.size()){
			cout << "Problem" << endl;
			exit(1);
		}
		else{
			double numerator = 0.0;
			double denominator = BM25ScoreList.size();
			double RMSDResult = 0.0;
			for(int i=0; i< BM25ScoreList.size(); i++){
				numerator += pow((BM25ScoreList[i] - BM25ScoreQuantizedScoreList[i]),2);
			}
			RMSDResult = sqrt(numerator/denominator);
			cout << "RMSDResult:" << RMSDResult << endl;
			outputFileHandler << RMSDResult;
			outputFileHandler << ",";

		}

		//Similarity Mesaure Method 2
		//Let's compute the Cosine similarity here.
		//The fomula is based on: http://en.wikipedia.org/wiki/Root-mean-square_deviation
		if (BM25ScoreList.size() != BM25ScoreQuantizedScoreList.size()){
			cout << "Problem" << endl;
			exit(1);
		}
		else{
			double numerator = 0.0;
			double denominator = 0.0;
			double denominatorPart1 = 0.0;
			double denominatorPart2 = 0.0;
			double consineSimilary = 0.0;

			for(int i=0; i< BM25ScoreList.size(); i++){
				numerator += BM25ScoreList[i] * BM25ScoreQuantizedScoreList[i];

				denominatorPart1 += pow(BM25ScoreList[i],2);
				denominatorPart2 += pow(BM25ScoreQuantizedScoreList[i],2);
			}

			denominatorPart1 = sqrt(denominatorPart1);
			denominatorPart2 = sqrt(denominatorPart2);
			denominator = denominatorPart1 * denominatorPart2;

			consineSimilary = numerator/denominator;

			cout << "Consine Similary:" << consineSimilary << endl;

			outputFileHandler << consineSimilary;
			outputFileHandler << "\n";

		}
	}
	outputFileHandler.close();
	*/

	return 0;
}
